/* 
* 版权所有 2015 魔视智能科技(上海)有限公司
* Copyright (c) 2015,Motovis Intelligent Technologies (Shanghai) Co.,Ltd
* 魔视智能公司秘密
* Motovis Intelligent Confidential Proprietary
* 文件名称：update.c
* 摘要: 系统升级文件
* 版本: V1.0.0.0
* 作者: zhangwenjian
* 完成日期: 2018年3月3日
* 历史记录：
*/

#ifndef _UPDATE_COMMONE_H_
#define _UPDATE_COMMONE_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <termios.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <dirent.h>
#include <syslog.h>
#include <linux/watchdog.h>
#include <mtd/mtd-user.h>

#include <sys/un.h>
#include <errno.h>

#define SD_CARD_MOUNTED		1
#define SD_CARD_UNMOUNTED		2

#define PAGE_SIZE	4096UL
#define PAGE_MASK	(PAGE_SIZE - 1)

/*part marker*/
#define PART_MARKER		0xabcddcba

#define EVERY_WRITE_LEN		0x10000
#define PART_MAX_NUM		12

/*system update_flag*/
#define NO_UPDATE			0x1
#define HAVE_UPDATE			0x2
#define TRY_FIRST_UPDATE	0x3
#define TRY_SECOND_UPDATE	0x4
#define TRY_THREE_UPDATE	0x5
#define FAILED_UPDATE		0x6
#define SUCCESSED_UPDATE	0x7

#define OTA_UPDATE	0x1
#define OTA_REBOOT	0x1

#define FILE_200M (200 * 1024 *1024)
#define FILE_1024M (1024 * 1024 *1024)


/*BOOT flag*/
#define START_FROM_FIRST	0x0
#define START_FROM_SECOND	0x1

typedef struct core_version {
	char szHardwareVer[32]; 			//硬件版本
	char szSoftwareVer[32]; 			//软件件版本, ota版本，对外使用
	char szDtbVer[32];					//dtb版本
	char szKernelVer[32];				//kernel版本
	char szRootfsVer[32];				//szRootfsVer版本
	char szWeightVer[32];				//weight版本
	char szFpgaVer[32];					//fpga版本
	char szMcuVer[32];					//mcu版本
	char szAppVer[32];					//app版本，应用版本，所有应用共一个版本
	char szCanVer[32];
	char reserved[32*5];
	unsigned int nUpdateStat;			//升级写文件状态 0x1:升级文件写完成                 0xFE:升级文件未写完成
} DeviceCoreVersion;

typedef struct _DeviceInfoPart{
	unsigned int nParkMarker;			//分区标记
	unsigned int nCheckSum;				//校验和
	unsigned int nUpdateFlag;			//升级标志
	unsigned int nBootFlag;				//启动分区
	char szFlashID[20];					//spiflash ID
	char szDevSn[32];					//设备序列号
	char szBootVersion[32];				//BOOT.bin版本，包括uboot,fsbl
	DeviceCoreVersion aCoreVer[2];		//双备份版本结构
	char szWatchDogVer[32];				//看门狗程序
	char szReserved[32*9];				//保留, [0]:3次ota失败开机会自动进行ota; [4]:ota 标志，区别其他的升级方式; [8]:ota刷写完成，请求reboot的标志; [1]:0:update-A, other:update-B
} DeviceInfoPart;

typedef struct _PartInfo{
	char szPartLabel[32];
	char szPartMMCBlockDev[32];
	unsigned long nPartLength;
} PartInfo;

//========================================================soc transfer use start
typedef unsigned char UINT8;

typedef enum _rqs_state{
	RQS_OTA_NONE = 0x10,
	RQS_OTA_START, //触发升级
	RQS_OTA_FILE, //请求差分还原
	RCV_OTA_FILE_OK, //差分还原成功
	RCV_OTA_FILE_FAIL, //差分还原失败
	RCV_OTA_FILE_DOING, //差分还原进行中
	RQS_OTA_REBOOT, //请求reboot
}rqs_state;

enum OTAUpgradeStatus //升级状态
{
    E_OTAUpgradeStatusInit = 0, //上电初始化中
    E_OTAUpgradeStatusIdle = 1, //空闲
    E_OTAUpgradeStatusUpgrading, //升级中, ota
    E_OTAUpgradeStatusSuccessful, //升级成功
    E_OTAUpgradeStatusFailed, //升级失败
    E_OTAUpgradeStatusBusy, //资源占用, other way to update software
};
typedef struct{
    UINT8 nReboot; // 0:normal start, 1:reboot
    UINT8 nStatus;//升级状态
    UINT8 nValue;//升级进度 0 ~100
}UpgradeInfo; //mv_update -> mv_ota

typedef struct{
    UINT8 sPackagePath[40];
    UINT8 sBaselinePath[40];
    UINT8 sCachePath[40];
}BsdiffInfo; //mv_update -> mv_ota


enum BsdiffStatus //升级状态
{
    E_BsdiffStatusProcessing = 1,//还原中
    E_BsdiffStatusSuccessful = 2,//还原成功
    E_BsdiffStatusFailed = 3,//还原失败
};

typedef struct{
    UINT8 value; /*0 ~ 100*/
    UINT8 nStatus;//还原状态
}BsdiffProcessStatus; //mv_ota -> mv_update

enum UpgradeMvUpdate2MvOtaCmd
{
    E_UpgradeMvUpdate2MvOtaCmd_UpgradeStatusResp = 1,//反馈升级状态
    E_UpgradeMvUpdate2MvOtaCmd_BsdiffReq = 2,//请求差分还原系统
    E_UpgradeMvUpdate2MvOtaCmd_RebootReq = 3//请求重启系统
};

enum  UpgradeMvOta2MvUpdateCmd
{
    E_UpgradeMvOta2MvUpdateCmd_StartUpgradeReq = 1,//开始升级请求
    E_UpgradeMvOta2MvUpdateCmd_BsdiffResp = 2,//反馈差分还原状态
    E_UpgradeMvOta2MvUpdateCmd_HandshakeReq = 3,//握手请求
};

/*
1 反馈升级状态 E_UpgradeMvUpdate2MvOtaCmd_UpgradeStatusResp
nDataLen = sizeof(UpgradeInfo)
data[0]即UpgradeInfo的首地址

2 请求差分还原 E_UpgradeMvUpdate2MvOtaCmd_BsdiffReq
nDataLen = sizeof(BsdiffInfo)
data[0]即BsdiffInfo的首地址

3 请求重启系统 E_UpgradeMvUpdate2MvOtaCmd_RebootReq
nDataLen = 0;
*/
#define BUF_SIZE 125

typedef struct _MvUpdate2MvOtaNetData_
{
    UINT8 nType; //数据包的类型 :固定是 0x01
    UINT8 nCmd;//命令
    UINT8 nDataLen;//数据包长度(0 ~ 125)
    UINT8 data[BUF_SIZE];
}MvUpdate2MvOtaNetData;

typedef struct _MvOta2MvUpdateNetData_
{
    UINT8 nType; //数据包的类型 :固定是 0x02
    UINT8 nCmd;//命令
    UINT8 nDataLen;//数据包长度(0 ~ 125)
    UINT8 data[BUF_SIZE];
}MvOta2MvUpdateNetData;

//========================================================soc transfer use end

int VersionInit(DeviceInfoPart *pInfo);
void ReadVersionFromIni(DeviceInfoPart *pInfo);
void WriteVersionToIni(DeviceInfoPart *pInfo);
int ReadMMCInfo(void);
int GetSDStatus(void);
int IsSdBurnMode(void);
int MountFileSystem(void);
int SetInfoPart(DeviceInfoPart *pInfo);
int GetInfoPart(DeviceInfoPart *pInfo);
int CheckDeviceInfo(DeviceInfoPart *pInfo);
int UpdateToPart(const char *pFileName, const char *pPartName);
int CopyFileToFile(const char *pSrcFile, const char *pDstFile);
int CopyPartToPart(const char *pSrcPartName, const char *pDstPartName);
int MountExt4(const char *pPartName, const char *pPartDir, int nRoFlag);
int UpdateSystemRunStat(void);
int ReadVersion(const char *pName, char *pVersion, char *path);
int GetVersionInfoLine(unsigned int nNum, char *pVersion, unsigned int nSize);
int DumpInfoPart(DeviceInfoPart *pInfoPart);
void SetUpdateProgress(int nUpdateProgress);
int GetUpdateProgress(void);
int SaveDdrFile(const char *pFileName, char *pFileBuf, int nFileLen);
int FlashLock(void);
int FlashUnlock(void);
unsigned int GetZipFileSize(const char *pFileName);

int UpdateInit();
int UpdateServerInit();
char GetRequestState(void);
void SetRequestState(char state);
void PthreadMutexInit(void);
void PthreadMutexDeinit(void);
int UpdateServerInit();


/* communicotion with socket client */
char GetOtaState(void);
void SetOtaState(char state);
int MySystem(const char *cmd);


#define DEBUG(fmt, ...)  \
	do { \
		printf("%s:%d " fmt , __func__, __LINE__, ##__VA_ARGS__); \
		syslog(LOG_WARNING, "%s:%d " fmt , __func__, __LINE__, ##__VA_ARGS__); \
	} while (0)
#endif


